package example.Assignment1;

import jade.core.Agent;
import jade.core.behaviours.Behaviour;
import jade.core.behaviours.SimpleBehaviour;
import jade.lang.acl.ACLMessage;
import org.rosuda.REngine.REXP;
import org.rosuda.REngine.REXPMismatchException;
import org.rosuda.REngine.Rserve.RConnection;
import org.rosuda.REngine.Rserve.RserveException;

import java.io.File;
import java.util.Arrays;

public class Rec_classify extends Agent {
    static double[][] Confusion;
    static Double Accuracy;
    static String[] Precision;
    static Integer bestK;
    static String location;
    @Override
    protected void setup() {
        Behaviour b = new SimpleBehaviour() {
            boolean finished = false;
            @Override
            public void action() {
                ACLMessage acl1 = receive();
                if(acl1!=null) {
                    System.out.println("receiving");
                    doWait(2000);
                    try {
                        RConnection reconnect = new RConnection("127.0.0.1");

                        REXP x = reconnect.eval("R.version.string");
                        System.out.println(x.asString());

                        //依赖
                        reconnect.eval("library(factoextra)\n" +
                                "library(NbClust)\n" +
                                "library(class)\n" +
                                "library(caret)\n" +
                                "library(lattice)\n" +
                                "library(ggplot2)\n" +
                                "library(randomForest)\n" +
                                "library(plyr)\n" +
                                "library(e1071)");

                        //读取文件
                        File file1 = new File(acl1.getContent());
                        location = String.valueOf(file1.getAbsoluteFile());
                        String[] sd = new String[1];
                        sd[0] = "\\";
                        location = detection(location,sd);
//            System.out.println(location);
                        reconnect.eval("dd <- read.table('" + location + "', header = T, sep = \",\")");

                        //k-fold
                        reconnect.eval("set.seed(1234)\n" +
                                "index_dd <- createDataPartition(dd$UNS, p=0.80, list = F, times = 1)\n" +
                                "df_dd <- as.data.frame(dd)\n" +
                                "train_df_dd <- df_dd[index_dd,]\n" +
                                "test_df_dd <- df_dd[-index_dd,]");

                        reconnect.eval("ctrlspecs_dd <- trainControl(method = \"cv\", number = 10,\n" +
                                "                    savePredictions = \"all\")");
                        reconnect.eval("set.seed(1234)");
                        reconnect.eval("model1_dd <- train(UNS ~ .,\n" +
                                "                data = train_df_dd,\n" +
                                "                method = \"knn\", \n" +
                                "                trControl = ctrlspecs_dd)");
                        bestK = reconnect.eval("model1_dd$finalModel$k").asInteger();

                        //get the Precision (exactness of a mode) in all 3 kinds of K
                        reconnect.eval("results_dd <- model1_dd$results");
                        Precision =  reconnect.eval("results_dd[,1]").asStrings();
                        String[] colnames = reconnect.eval("results_dd[,2]").asStrings();


                        //knn
                        reconnect.eval("set.seed(1234)\n" +
                                "idx <- sample(2, nrow(dd),replace = T, prob = c(0.80,0.20))\n" +
                                "dd.trainSet <- dd[idx==1, 1:5]\n" +
                                "dd.testSet <- dd[idx==2, 1:5]\n" +
                                "dd.trainLabels <- dd[idx==1, 6]\n" +
                                "dd.testLabels <- dd[idx==2, 6]");
                        reconnect.eval("dd_pred <- knn(train = dd.trainSet, test = dd.testSet, cl = dd.trainLabels, k=" + bestK +")");
                        Confusion = reconnect.eval("confusionTable_dd <- print(table(dd_pred, dd.testLabels))").asDoubleMatrix();
                        Accuracy = reconnect.eval("accuracy_dd <- (sum(diag(confusionTable_dd))/sum(confusionTable_dd))").asDouble();

                        System.out.println("The best K for knn is:");
                        System.out.println(bestK);
                        System.out.println("K = " + bestK + ", the knn model accuracy and the Confusion matrix data");
                        System.out.println(Accuracy);
                        for (int i = 0; i < Confusion.length; i++) {
                            System.out.println(Arrays.toString(Confusion[i]));
                        }
                        System.out.println("The Precision (exactness of knn) in 3 kinds of K");
                        System.out.println(Arrays.toString(Precision));
                        System.out.println(Arrays.toString(colnames));

                    } catch (RserveException | REXPMismatchException e) {
                        e.printStackTrace();
                    }
                    finished = true;
                    myAgent.doDelete();
                }
                else {
                    System.out.println(getLocalName()+" does not receive a message");
                    block();//如果没有消息，则阻塞行为
                }
            }

            @Override
            public boolean done() {
                return finished;
            }
        };
        addBehaviour(b);
    }

    public static String detection(String content,String[] badString){
        for (int i = 0; i <badString.length ; i++) {
            content= index(content,badString[i]);
        }
        return content;
    }

    private static String index(String content,String badString){
        if(content.equals("")||badString.equals("")) {
            return content;
        }
        int index = content.indexOf(badString);
        String newString="";
        if(index!=-1){
            String newString1=content.substring(0,index);
            String newString2=content.substring(index+badString.length());
            String hindString="";
            for (int i = 0; i < badString.length() ; i++) {
                hindString = hindString + "//";
            }
            newString = newString1 + hindString + newString2;
            return index(newString,badString);
        }
        return content;
    }
}
